from flask import render_template, jsonify, request, redirect, url_for, flash, g
from datetime import datetime
from models import Todo
from user import LoginForm
from __init__ import app, sockets, login_manager, flask_login
from websocket.message import Ws, MessageType
import models
from werkzeug.security import generate_password_hash
import time
from flask_login import current_user
import json
clients = {}


@sockets.route('/websocket/<mac>/<name>')
def web_socket(ws, mac, name):
    print(mac + ' connected...')

    if not ws.closed:
        try:
            todo_list = Todo.objects(mac=mac).first()  # 先查找
            if not todo_list:
                print("There is no record in the database.")
                print("add this mac %s in the database." % mac)
                todo = Todo(content=name, mac=mac, time=datetime.now())
                todo.save()
            clients[mac] = Ws(ws, mac)
            # 在获取设备列表前发送查询当前列表信息
            for mac in clients:
                print('client mac : ', mac)
                clients[mac].send(json.dumps({"action": "get_device_list"}))
            clients[mac].run_forever()
        # except:
        # raise
        finally:
            print(mac + " disconnected...")
            clients.pop(mac)
    else:
        # return HttpResponse("This only accept ws")
        pass


@login_manager.user_loader
def load_user(user_id):
    return models.User.objects(id=user_id).first()


# @app.route('/tables', methods=['GET', 'POST'])
# def tables():
#     if request.method == 'GET':
#         return render_template('tables.html')


# @app.route('/websocket', methods=['GET', 'POST'])
# def websocket():
#     if request.method == 'GET':
#         return render_template('websocket.html')


@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html')


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')

    form = LoginForm(request.form)
    if request.method == 'POST' and form.validate_name():
        user = form.get_user()
        remember = form.remember_me.data
        print(remember)
        flask_login.login_user(user, remember=remember, force=False, fresh=True)
        flash("Logged in!")
        return redirect(url_for('.protected'))
    # mleaf rain
    return jsonify(status="UserName Or Password Error")


# 登陆后路由
@app.route('/protected')
@flask_login.login_required
def protected():
    return render_template('protected.html')
    # return 'Logged in as: ' + flask_login.current_user.id


@app.route('/pages/tables.html')
@flask_login.login_required
def tables():
    return render_template('pages/tables.html')


@app.route('/pages/tables-zigbee.html')
# @flask_login.login_required
def tables_zigbee():
    return render_template('pages/tables-zigbee.html')


@app.route('/pages/index.html')
@flask_login.login_required
def pages():
    return render_template('pages/index.html')


@app.route('/pages/blank.html')
@flask_login.login_required
def blank():
    return render_template('pages/blank.html')


@app.route('/pages/buttons.html')
@flask_login.login_required
def buttons():
    return render_template('pages/buttons.html')


@app.route('/pages/flot.html')
@flask_login.login_required
def flot():
    return render_template('pages/flot.html')


@app.route('/pages/forms.html')
@flask_login.login_required
def forms():
    return render_template('pages/forms.html')


@app.route('/pages/grid.html')
@flask_login.login_required
def grid():
    return render_template('pages/grid.html')


@app.route('/pages/icons.html')
@flask_login.login_required
def icons():
    return render_template('pages/icons.html')


@app.route('/pages/morris.html')
@flask_login.login_required
def morris():
    return render_template('pages/morris.html')


@app.route('/pages/notifications.html')
@flask_login.login_required
def notifications():
    return render_template('pages/notifications.html')


@app.route('/pages/panels-wells.html')
@flask_login.login_required
def panels():
    return render_template('pages/panels-wells.html')


@app.route('/pages/typography.html')
@flask_login.login_required
def typography():
    return render_template('pages/typography.html')


@app.route('/logout')
def logout():
    flask_login.logout_user()
    return render_template('login.html')


@app.route('/adduser', methods=['POST'])
def add_user():
    form = request.form  # 数据通过表单传递过来
    username = form.get('username')
    password = form.get('password')
    email = form.get('email')
    description = form.get('description')
    password_hash = generate_password_hash(password)  # generate password hash
    user = models.User(username=username, password=password_hash, email=email, description=description)
    user.save()
    return jsonify(status="success")


@app.route('/sendto/<device_id>', methods=['POST'])
def sendto(device_id):
    form = request.form
    sendto_msg = form.get('msg')
    clients[device_id].send(sendto_msg)
    return jsonify(status="success")


@app.route('/add', methods=['POST'])
def add():
    form = request.form  # 数据通过表单传递过来
    content = form.get('content')
    mac = form.get('mac')
    print(content)
    todo = Todo(content=content, mac=mac, time=datetime.now())
    todo.save()
    return jsonify(status="success")


@app.route('/delete/<string:todo_id>', methods=['POST'])
def delete(todo_id):
    todo = Todo.objects.get_or_404(id=todo_id)
    todo.delete()
    return jsonify(status="success")


@app.route('/update', methods=['POST'])
def update():
    form = request.form
    todo_id = form.get('id')
    status = form.get('status')
    todo = Todo.objects.get_or_404(id=todo_id)
    # if int(status) == 0:
    #     clients[todo.mac].send(json.dumps({"action":"control_device", "destination":"toGateWay","source":"app","gateWayDeviceId":"e424e7000fc8","requestId":"3fa7665d-9788-4852-8336-d7933d8cd1b2","command":"off","data":[{"deviceType":"1103","deviceAddress":"000D6F000ABF9DCF","deviceStatus":"on"}]}))
    #     # clients[todo.mac].send(json.dumps({"action": "trun off", "status": "success"}))
    # else:
    #     clients[todo.mac].send(json.dumps({"action":"control_device", "destination":"toGateWay","source":"app","gateWayDeviceId":"e424e7000fc8","requestId":"3fa7665d-9788-4852-8336-d7933d8cd1b2","command":"on","data":[{"deviceType":"1103","deviceAddress":"000D6F000ABF9DCF","deviceStatus":"off"}]}))
    #     # clients[todo.mac].send(json.dumps({"action": "trun on", "status": "success"}))
    todo.status = status  # 修改查找到的todo的状态
    todo.save()
    return jsonify(status="success")


@app.route('/list', methods=['GET'])
def query():
    todo_list = Todo.objects.order_by('-time')  # 排序

    return jsonify(status="success", aaData=[todo.to_json() for todo in todo_list])


@app.route('/get_zigbee_list', methods=['POST'])
def get_zigbee_list():
    form = request.form
    router_mac = form.get('mac')
    print(router_mac)
    reply = clients[router_mac].get_reply(MessageType.GET_DEVICE_LIST)
    print(reply)
    clients[router_mac].send(json.dumps({"action": "get_device_list"}))  # 查询列表
    return jsonify(status="success", data=reply)


@app.route('/zigbee_list', methods=['GET'])
def zigbee_list():

    reply = {}
    for mac in clients:
        if mac is not None:
            print('client mac : ', mac)
            reply = clients[mac].get_reply(MessageType.GET_DEVICE_LIST)
        else:
            clients[mac].send(json.dumps({"action": "get_device_list"}))  # 查询列表

    return jsonify(status="success", gateWayAddress=reply['gateWayDeviceId'], data=reply['data'])


@app.route('/ctrl_zigbee_list', methods=['GET'])
def ctrl_zigbee_list():

    reply = {}
    for mac in clients:
        if mac is not None:
            print('client mac : ', mac)
            reply = clients[mac].get_reply(MessageType.CONTROL_DEVICE)
        else:
            clients[mac].send(json.dumps({"action": "get_device_list"}))  # 查询列表

    return jsonify(status="success", gateWayAddress=reply['gateWayDeviceId'], data=reply['data'])


@app.route('/ctrl_zigbee_device', methods=['POST'])
def ctrl_zigbee_device():
    form = request.form
    device_address = form.get('deviceAddress')
    device_type = form.get('deviceType')
    endpoint_id = form.get('endpoint_id')
    command = form.get('command')
    print('ctrl zigbee device device address:' + device_address)
    print('ctrl zigbee device device type:' + device_type)
    print('ctrl zigbee device endpoint id:' + endpoint_id)
    message = {
        "action": "control_device",
        "destination": "toGateWay",
        "source": "app",
        "gateWayDeviceId": "e424e7000fc8",
        "requestId": "3fa7665d-9788-4852-8336-d7933d8cd1b2",
        "command": command,
        "data": [{
            "deviceType": device_type,
            "deviceAddress": device_address,
            "deviceStatus": "off"
        }]
    }
    message = bytes(json.dumps(message).encode())
    clients["e624e7000fc8"].send(message)
    return jsonify(status="success")

# if __name__ == '__main__':
#     app.run()
if __name__ == "__main__":
    print('start websocket server')

    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler

    server = pywsgi.WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
    server.serve_forever()
